<!DOCTYPE html>
<script src=../../resources/testharness.js></script>
<script src=../../resources/testharnessreport.js></script>
<script>

// This test verifies that MediaRecorder can be created or not with different
// bitrates for video, audio and for both [1]. It checks a few numerical bitrate
// allocations, asserting that individual bit rates are honored or clamped as
// expected, and how the overall bitsPerSecond is divided into video and audio
// bitrates.
// [1] https://rawgit.com/w3c/mediacapture-record/master/MediaRecorder.html#MediaRecorderOptions

function makeExpectedBitrateAsyncTest(options, testName, expectedBps) {
  async_test(function(test) {
    const constraints = {video: true,  audio: true};

    const gotStream = test.step_func(function(stream) {
      var recorder = new MediaRecorder(stream, options);
      assert_equals(recorder.videoBitsPerSecond, expectedBps.video, 'video');
      assert_equals(recorder.audioBitsPerSecond, expectedBps.audio, 'audio');

      test.done();
    });

    const onError = test.unreached_func('Error creating MediaStream.');
    navigator.webkitGetUserMedia(constraints, gotStream, onError);
  }, testName);
};

const kTooSmallBps = 1000;
const kTooLargeBps = 1000000000;

const kOkVideoBps = 500000;
const kMinVideoBps = 100000;
// Note that unspecified audio bitrates are not clamped to a minimum.
makeExpectedBitrateAsyncTest({ videoBitsPerSecond : kOkVideoBps },
                             'Video bitrate OK',
                             { video : kOkVideoBps, audio : 0 });
makeExpectedBitrateAsyncTest({ videoBitsPerSecond : kTooSmallBps },
                             'Video bitrate clamped to minimum',
                             { video : kMinVideoBps, audio : 0 });
makeExpectedBitrateAsyncTest({ videoBitsPerSecond : 0 },
                             'Video bitrate explicitly set to 0 is clamped',
                             { video : kMinVideoBps, audio : 0 });

const kOkAudioBps = 10000;
const kMinAudioBps = 6000;  // https://www.opus-codec.org/
const kMaxAudioBps = 128000;
// Note that unspecified video bitrates are not clamped to a minimum.
makeExpectedBitrateAsyncTest({ audioBitsPerSecond : kOkAudioBps },
                             'Audio bitrate OK',
                             { audio : kOkAudioBps, video : 0 });
makeExpectedBitrateAsyncTest({ audioBitsPerSecond : kTooSmallBps },
                             'Audio bitrate clamped to minimum',
                             { audio : kMinAudioBps, video : 0 });
makeExpectedBitrateAsyncTest({ audioBitsPerSecond : kTooLargeBps },
                             'Audio bitrate clamped to maximum',
                             { audio : kMaxAudioBps , video : 0});
makeExpectedBitrateAsyncTest({ audioBitsPerSecond : 0 },
                             'Audio bitrate explicitly 0 is clamped',
                             { audio : kMinAudioBps, video : 0 });

makeExpectedBitrateAsyncTest({},
                             'Unspecified bitrates are not clamped',
                             { video : 0, audio : 0 });

makeExpectedBitrateAsyncTest({ videoBitsPerSecond : kOkVideoBps, audioBitsPerSecond : kOkAudioBps },
                             'Video and audio bitrates OK',
                             { video : kOkVideoBps, audio : kOkAudioBps });

const kOkOverallBps = 120000;
makeExpectedBitrateAsyncTest({ bitsPerSecond : kOkOverallBps },
                             'Overall bitrate OK (divided 90/10 video/audio)',
                             { video : kOkOverallBps * 0.9, audio : kOkOverallBps * 0.1 });
makeExpectedBitrateAsyncTest({ videoBitsPerSecond : kOkVideoBps, bitsPerSecond : kOkOverallBps },
                             'Overall bitrate OK, w/ explicit video bitrate ignored',
                             { video : kOkOverallBps * 0.9, audio : kOkOverallBps * 0.1 });
makeExpectedBitrateAsyncTest({ audioBitsPerSecond : kOkAudioBps, bitsPerSecond : kOkOverallBps },
                             'Overall bitrate OK, w/ explicit audio bitrate ignored',
                             { video : kOkOverallBps * 0.9, audio : kOkOverallBps * 0.1 });

makeExpectedBitrateAsyncTest({ bitsPerSecond : 10E6 },
                             'Overall bitrate leads to audio clamped to its maximum',
                             { video : 10E6 - kMaxAudioBps, audio : kMaxAudioBps });
makeExpectedBitrateAsyncTest({ bitsPerSecond : (kMinVideoBps - 1E3) },
                             'Overall bitrate leads to video clamped to its minimum',
                             { video : kMinVideoBps, audio : (kMinVideoBps - 1E3) * 0.1 });
makeExpectedBitrateAsyncTest({ bitsPerSecond : kTooSmallBps },
                             'Overall bitrate leads to both audio and video clamped to min',
                             { video : kMinVideoBps, audio : kMinAudioBps });

makeExpectedBitrateAsyncTest({ videoBitsPerSecond: kOkVideoBps, bitsPerSecond: 0 },
                             'Overall bitrate 0 overrides specified video bitrate',
                             { video: kMinVideoBps, audio: kMinAudioBps });
makeExpectedBitrateAsyncTest({ audioBitsPerSecond: kOkAudioBps, bitsPerSecond: 0 },
                             'Overall bitrate 0 overrides specified audio bitrate',
                             { video: kMinVideoBps, audio: kMinAudioBps });

const kMaxInt32Value = Math.pow(2, 31) - 1;
makeExpectedBitrateAsyncTest({ bitsPerSecond : -1 },
                             'Overall bitrate too large is clamped',
                             { video : kMaxInt32Value - kMaxAudioBps, audio : kMaxAudioBps});

</script>
